home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / ultqsrc.zip / QCC.C < prev    next >
C/C++ Source or Header  |  1996-09-09  |  25KB  |  1,116 lines

  1.  
  2. #include "qcc.h"
  3.  
  4.  
  5. char        destfile[1024];
  6.  
  7. float        pr_globals[MAX_REGS];
  8. int            numpr_globals;
  9.  
  10. char        strings[MAX_STRINGS];
  11. int            strofs;
  12.  
  13. dstatement_t    statements[MAX_STATEMENTS];
  14. int            numstatements;
  15. int            statement_linenums[MAX_STATEMENTS];
  16.  
  17. dfunction_t    functions[MAX_FUNCTIONS];
  18. int            numfunctions;
  19.  
  20. ddef_t        globals[MAX_GLOBALS];
  21. int            numglobaldefs;
  22.  
  23. ddef_t        fields[MAX_FIELDS];
  24. int            numfielddefs;
  25.  
  26. char        precache_sounds[MAX_SOUNDS][MAX_DATA_PATH];
  27. int            precache_sounds_block[MAX_SOUNDS];
  28. int            numsounds;
  29.  
  30. char        precache_models[MAX_MODELS][MAX_DATA_PATH];
  31. int            precache_models_block[MAX_SOUNDS];
  32. int            nummodels;
  33.  
  34. char        precache_files[MAX_FILES][MAX_DATA_PATH];
  35. int            precache_files_block[MAX_SOUNDS];
  36. int            numfiles;
  37.  
  38.  
  39. /*
  40. =================
  41. BspModels
  42.  
  43. Runs qbsp and light on all of the models with a .bsp extension
  44. =================
  45. */
  46. void BspModels (void)
  47. {
  48.     int        p;
  49.     char    *gamedir;
  50.     int        i;
  51.     char    *m;
  52.     char    cmd[1024];
  53.     char    name[256];
  54.  
  55.     p = CheckParm ("-bspmodels");
  56.     if (!p)
  57.         return;
  58.     if (p == myargc-1)
  59.         Error ("-bspmodels must preceed a game directory");
  60.     gamedir = myargv[p+1];
  61.     
  62.     for (i=0 ; i<nummodels ; i++)
  63.     {
  64.         m = precache_models[i];
  65.         if (strcmp(m+strlen(m)-4, ".bsp"))
  66.             continue;
  67.         strcpy (name, m);
  68.         name[strlen(m)-4] = 0;
  69.         sprintf (cmd, "qbsp %s/%s ; light -extra %s/%s", gamedir, name, gamedir, name);
  70.         system (cmd);
  71.     }
  72. }
  73.  
  74. // CopyString returns an offset from the string heap
  75. int    CopyString (char *str)
  76. {
  77.     int        old;
  78.     
  79.     old = strofs;
  80.     strcpy (strings+strofs, str);
  81.     strofs += strlen(str)+1;
  82.     return old;
  83. }
  84.  
  85. void PrintStrings (void)
  86. {
  87.     int        i, l, j;
  88.     
  89.     for (i=0 ; i<strofs ; i += l)
  90.     {
  91.         l = strlen(strings+i) + 1;
  92.         printf ("%5i : ",i);
  93.         for (j=0 ; j<l ; j++)
  94.         {
  95.             if (strings[i+j] == '\n')
  96.             {
  97.                 putchar ('\\');
  98.                 putchar ('n');
  99.             }
  100.             else
  101.                 putchar (strings[i+j]);
  102.         }
  103.         printf ("\n");
  104.     }
  105. }
  106.  
  107.  
  108. void PrintFunctions (void)
  109. {
  110.     int        i,j;
  111.     dfunction_t    *d;
  112.     
  113.     for (i=0 ; i<numfunctions ; i++)
  114.     {
  115.         d = &functions[i];
  116.         printf ("%s : %s : %i %i (", strings + d->s_file, strings + d->s_name, d->first_statement, d->parm_start);
  117.         for (j=0 ; j<d->numparms ; j++)
  118.             printf ("%i ",d->parm_size[j]);
  119.         printf (")\n");
  120.     }
  121. }
  122.  
  123. void PrintFields (void)
  124. {
  125.     int        i;
  126.     ddef_t    *d;
  127.     
  128.     for (i=0 ; i<numfielddefs ; i++)
  129.     {
  130.         d = &fields[i];
  131.         printf ("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
  132.     }
  133. }
  134.  
  135. void PrintGlobals (void)
  136. {
  137.     int        i;
  138.     ddef_t    *d;
  139.     
  140.     for (i=0 ; i<numglobaldefs ; i++)
  141.     {
  142.         d = &globals[i];
  143.         printf ("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
  144.     }
  145. }
  146.  
  147.  
  148. void InitData (void)
  149. {
  150.     int        i;
  151.     
  152.     numstatements = 1;
  153.     strofs = 1;
  154.     numfunctions = 1;
  155.     numglobaldefs = 1;
  156.     numfielddefs = 1;
  157.     
  158.     def_ret.ofs = OFS_RETURN;
  159.     for (i=0 ; i<MAX_PARMS ; i++)
  160.         def_parms[i].ofs = OFS_PARM0 + 3*i;
  161. }
  162.  
  163.  
  164. void WriteData (int crc)
  165. {
  166.     def_t        *def;
  167.     ddef_t        *dd;
  168.     dprograms_t    progs;
  169.     int            h;
  170.     int            i;
  171.  
  172.     for (def = pr.def_head.next ; def ; def = def->next)
  173.     {
  174.         if (def->type->type == ev_function)
  175.         {
  176. //            df = &functions[numfunctions];
  177. //            numfunctions++;
  178.  
  179.         }
  180.         else if (def->type->type == ev_field)
  181.         {
  182.             dd = &fields[numfielddefs];
  183.             numfielddefs++;
  184.             dd->type = def->type->aux_type->type;
  185.             dd->s_name = CopyString (def->name);
  186.             dd->ofs = G_INT(def->ofs);
  187.         }
  188.         dd = &globals[numglobaldefs];
  189.         numglobaldefs++;
  190.         dd->type = def->type->type;
  191.         if ( !def->initialized
  192.         && def->type->type != ev_function
  193.         && def->type->type != ev_field
  194.         && def->scope == NULL)
  195.             dd->type |= DEF_SAVEGLOBGAL;
  196.         dd->s_name = CopyString (def->name);
  197.         dd->ofs = def->ofs;
  198.     }
  199.  
  200. //PrintStrings ();
  201. //PrintFunctions ();
  202. //PrintFields ();
  203. //PrintGlobals ();
  204. strofs = (strofs+3)&~3;
  205.  
  206.     printf ("%6i strofs\n", strofs);
  207.     printf ("%6i numstatements\n", numstatements);
  208.     printf ("%6i numfunctions\n", numfunctions);
  209.     printf ("%6i numglobaldefs\n", numglobaldefs);
  210.     printf ("%6i numfielddefs\n", numfielddefs);
  211.     printf ("%6i numpr_globals\n", numpr_globals);
  212.     
  213.     h = SafeOpenWrite (destfile);
  214.     SafeWrite (h, &progs, sizeof(progs));
  215.  
  216.     progs.ofs_strings = lseek (h, 0, SEEK_CUR);
  217.     progs.numstrings = strofs;
  218.     SafeWrite (h, strings, strofs);
  219.  
  220.     progs.ofs_statements = lseek (h, 0, SEEK_CUR);
  221.     progs.numstatements = numstatements;
  222.     for (i=0 ; i<numstatements ; i++)
  223.     {
  224.         statements[i].op = LittleShort(statements[i].op);
  225.         statements[i].a = LittleShort(statements[i].a);
  226.         statements[i].b = LittleShort(statements[i].b);
  227.         statements[i].c = LittleShort(statements[i].c);
  228.     }
  229.     SafeWrite (h, statements, numstatements*sizeof(dstatement_t));
  230.  
  231.     progs.ofs_functions = lseek (h, 0, SEEK_CUR);
  232.     progs.numfunctions = numfunctions;
  233.     for (i=0 ; i<numfunctions ; i++)
  234.     {
  235.     functions[i].first_statement = LittleLong (functions[i].first_statement);
  236.     functions[i].parm_start = LittleLong (functions[i].parm_start);
  237.     functions[i].s_name = LittleLong (functions[i].s_name);
  238.     functions[i].s_file = LittleLong (functions[i].s_file);
  239.     functions[i].numparms = LittleLong (functions[i].numparms);
  240.     functions[i].locals = LittleLong (functions[i].locals);
  241.     }    
  242.     SafeWrite (h, functions, numfunctions*sizeof(dfunction_t));
  243.  
  244.     progs.ofs_globaldefs = lseek (h, 0, SEEK_CUR);
  245.     progs.numglobaldefs = numglobaldefs;
  246.     for (i=0 ; i<numglobaldefs ; i++)
  247.     {
  248.         globals[i].type = LittleShort (globals[i].type);
  249.         globals[i].ofs = LittleShort (globals[i].ofs);
  250.         globals[i].s_name = LittleLong (globals[i].s_name);
  251.     }
  252.     SafeWrite (h, globals, numglobaldefs*sizeof(ddef_t));
  253.  
  254.     progs.ofs_fielddefs = lseek (h, 0, SEEK_CUR);
  255.     progs.numfielddefs = numfielddefs;
  256.     for (i=0 ; i<numfielddefs ; i++)
  257.     {
  258.         fields[i].type = LittleShort (fields[i].type);
  259.         fields[i].ofs = LittleShort (fields[i].ofs);
  260.         fields[i].s_name = LittleLong (fields[i].s_name);
  261.     }
  262.     SafeWrite (h, fields, numfielddefs*sizeof(ddef_t));
  263.  
  264.     progs.ofs_globals = lseek (h, 0, SEEK_CUR);
  265.     progs.numglobals = numpr_globals;
  266.     for (i=0 ; i<numpr_globals ; i++)
  267.         ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
  268.     SafeWrite (h, pr_globals, numpr_globals*4);
  269.  
  270.     printf ("%6i TOTAL SIZE\n", (int)lseek (h, 0, SEEK_CUR));    
  271.  
  272.     progs.entityfields = pr.size_fields;
  273.  
  274.     progs.version = PROG_VERSION;
  275.     progs.crc = crc;
  276.     
  277. // byte swap the header and write it out
  278.     for (i=0 ; i<sizeof(progs)/4 ; i++)
  279.         ((int *)&progs)[i] = LittleLong ( ((int *)&progs)[i] );        
  280.     lseek (h, 0, SEEK_SET);
  281.     SafeWrite (h, &progs, sizeof(progs));
  282.     close (h);
  283.     
  284. }
  285.  
  286.  
  287.  
  288. /*
  289. ===============
  290. PR_String
  291.  
  292. Returns a string suitable for printing (no newlines, max 60 chars length)
  293. ===============
  294. */
  295. char *PR_String (char *string)
  296. {
  297.     static char buf[80];
  298.     char    *s;
  299.     
  300.     s = buf;
  301.     *s++ = '"';
  302.     while (string && *string)
  303.     {
  304.         if (s == buf + sizeof(buf) - 2)
  305.             break;
  306.         if (*string == '\n')
  307.         {
  308.             *s++ = '\\';
  309.             *s++ = 'n';
  310.         }
  311.         else if (*string == '"')
  312.         {
  313.             *s++ = '\\';
  314.             *s++ = '"';
  315.         }
  316.         else
  317.             *s++ = *string;
  318.         string++;
  319.         if (s - buf > 60)
  320.         {
  321.             *s++ = '.';
  322.             *s++ = '.';
  323.             *s++ = '.';
  324.             break;
  325.         }
  326.     }
  327.     *s++ = '"';
  328.     *s++ = 0;
  329.     return buf;
  330. }
  331.  
  332.  
  333.  
  334. def_t    *PR_DefForFieldOfs (gofs_t ofs)
  335. {
  336.     def_t    *d;
  337.     
  338.     for (d=pr.def_head.next ; d ; d=d->next)
  339.     {
  340.         if (d->type->type != ev_field)
  341.             continue;
  342.         if (*((int *)&pr_globals[d->ofs]) == ofs)
  343.             return d;
  344.     }
  345.     Error ("PR_DefForFieldOfs: couldn't find %i",ofs);
  346.     return NULL;
  347. }
  348.  
  349. /*
  350. ============
  351. PR_ValueString
  352.  
  353. Returns a string describing *data in a type specific manner
  354. =============
  355. */
  356. char *PR_ValueString (etype_t type, void *val)
  357. {
  358.     static char    line[256];
  359.     def_t        *def;
  360.     dfunction_t    *f;
  361.     
  362.     switch (type)
  363.     {
  364.     case ev_string:
  365.         sprintf (line, "%s", PR_String(strings + *(int *)val));
  366.         break;
  367.     case ev_entity:    
  368.         sprintf (line, "entity %i", *(int *)val);
  369.         break;
  370.     case ev_function:
  371.         f = functions + *(int *)val;
  372.         if (!f)
  373.             sprintf (line, "undefined function");
  374.         else
  375.             sprintf (line, "%s()", strings + f->s_name);
  376.         break;
  377.     case ev_field:
  378.         def = PR_DefForFieldOfs ( *(int *)val );
  379.         sprintf (line, ".%s", def->name);
  380.         break;
  381.     case ev_void:
  382.         sprintf (line, "void");
  383.         break;
  384.     case ev_float:
  385.         sprintf (line, "%5.1f", *(float *)val);
  386.         break;
  387.     case ev_vector:
  388.         sprintf (line, "'%5.1f %5.1f %5.1f'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
  389.         break;
  390.     case ev_pointer:
  391.         sprintf (line, "pointer");
  392.         break;
  393.     default:
  394.         sprintf (line, "bad type %i", type);
  395.         break;
  396.     }
  397.     
  398.     return line;
  399. }
  400.  
  401. /*
  402. ============
  403. PR_GlobalString
  404.  
  405. Returns a string with a description and the contents of a global,
  406. padded to 20 field width
  407. ============
  408. */
  409. char *PR_GlobalStringNoContents (gofs_t ofs)
  410. {
  411.     int        i;
  412.     def_t    *def;
  413.     void    *val;
  414.     static char    line[128];
  415.     
  416.     val = (void *)&pr_globals[ofs];
  417.     def = pr_global_defs[ofs];
  418.     if (!def)
  419. //        Error ("PR_GlobalString: no def for %i", ofs);
  420.         sprintf (line,"%i(???)", ofs);
  421.     else
  422.         sprintf (line,"%i(%s)", ofs, def->name);
  423.     
  424.     i = strlen(line);
  425.     for ( ; i<16 ; i++)
  426.         strcat (line," ");
  427.     strcat (line," ");
  428.         
  429.     return line;
  430. }
  431.  
  432. char *PR_GlobalString (gofs_t ofs)
  433. {
  434.     char    *s;
  435.     int        i;
  436.     def_t    *def;
  437.     void    *val;
  438.     static char    line[128];
  439.     
  440.     val = (void *)&pr_globals[ofs];
  441.     def = pr_global_defs[ofs];
  442.     if (!def)
  443.         return PR_GlobalStringNoContents(ofs);
  444.     if (def->initialized && def->type->type != ev_function)
  445.     {
  446.         s = PR_ValueString (def->type->type, &pr_globals[ofs]);
  447.         sprintf (line,"%i(%s)", ofs, s);
  448.     }
  449.     else
  450.         sprintf (line,"%i(%s)", ofs, def->name);
  451.     
  452.     i = strlen(line);
  453.     for ( ; i<16 ; i++)
  454.         strcat (line," ");
  455.     strcat (line," ");
  456.         
  457.     return line;
  458. }
  459.  
  460. /*
  461. ============
  462. PR_PrintOfs
  463. ============
  464. */
  465. void PR_PrintOfs (gofs_t ofs)
  466. {
  467.     printf ("%s\n",PR_GlobalString(ofs));
  468. }
  469.  
  470. /*
  471. =================
  472. PR_PrintStatement
  473. =================
  474. */
  475. void PR_PrintStatement (dstatement_t *s)
  476. {
  477.     int        i;
  478.     
  479.     printf ("%4i : %4i : %s ", (int)(s - statements), statement_linenums[s-statements], pr_opcodes[s->op].opname);
  480.     i = strlen(pr_opcodes[s->op].opname);
  481.     for ( ; i<10 ; i++)
  482.         printf (" ");
  483.         
  484.     if (s->op == OP_IF || s->op == OP_IFNOT)
  485.         printf ("%sbranch %i",PR_GlobalString(s->a),s->b);
  486.     else if (s->op == OP_GOTO)
  487.     {
  488.         printf ("branch %i",s->a);
  489.     }
  490.     else if ( (unsigned)(s->op - OP_STORE_F) < 6)
  491.     {
  492.         printf ("%s",PR_GlobalString(s->a));
  493.         printf ("%s", PR_GlobalStringNoContents(s->b));
  494.     }
  495.     else
  496.     {
  497.         if (s->a)
  498.             printf ("%s",PR_GlobalString(s->a));
  499.         if (s->b)
  500.             printf ("%s",PR_GlobalString(s->b));
  501.         if (s->c)
  502.             printf ("%s", PR_GlobalStringNoContents(s->c));
  503.     }
  504.     printf ("\n");
  505. }
  506.  
  507.  
  508. /*
  509. ============
  510. PR_PrintDefs
  511. ============
  512. */
  513. void PR_PrintDefs (void)
  514. {
  515.     def_t    *d;
  516.     
  517.     for (d=pr.def_head.next ; d ; d=d->next)
  518.         PR_PrintOfs (d->ofs);
  519. }
  520.  
  521.  
  522. /*
  523. ==============
  524. PR_BeginCompilation
  525.  
  526. called before compiling a batch of files, clears the pr struct
  527. ==============
  528. */
  529. void    PR_BeginCompilation (void *memory, int memsize)
  530. {
  531.     int        i;
  532.     
  533.     pr.memory = memory;
  534.     pr.max_memory = memsize;
  535.     
  536.     numpr_globals = RESERVED_OFS;
  537.     pr.def_tail = &pr.def_head;
  538.     
  539.     for (i=0 ; i<RESERVED_OFS ; i++)
  540.         pr_global_defs[i] = &def_void;
  541.         
  542. // link the function type in so state forward declarations match proper type
  543.     pr.types = &type_function;
  544.     type_function.next = NULL;
  545.     pr_error_count = 0;
  546. }
  547.  
  548. /*
  549. ==============
  550. PR_FinishCompilation
  551.  
  552. called after all files are compiled to check for errors
  553. Returns false if errors were detected.
  554. ==============
  555. */
  556. boolean    PR_FinishCompilation (void)
  557. {
  558.     def_t        *d;
  559.     boolean    errors;
  560.     
  561.     errors = false;
  562.     
  563. // check to make sure all functions prototyped have code
  564.     for (d=pr.def_head.next ; d ; d=d->next)
  565.     {
  566.         if (d->type->type == ev_function && !d->scope)// function parms are ok
  567.         {
  568. //            f = G_FUNCTION(d->ofs);
  569. //            if (!f || (!f->code && !f->builtin) )
  570.             if (!d->initialized)
  571.             {
  572.                 printf ("function %s was not defined\n",d->name);
  573.                 errors = true;
  574.             }
  575.         }
  576.     }
  577.  
  578.     return !errors;
  579. }
  580.  
  581. //=============================================================================
  582.  
  583. // FIXME: byte swap?
  584.  
  585. // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
  586. // and the initial and final xor values shown below...  in other words, the
  587. // CCITT standard CRC used by XMODEM
  588.  
  589. #define CRC_INIT_VALUE    0xffff
  590. #define CRC_XOR_VALUE    0x0000
  591.  
  592. static unsigned short crctable[256] =
  593. {
  594.     0x0000,    0x1021,    0x2042,    0x3063,    0x4084,    0x50a5,    0x60c6,    0x70e7,
  595.     0x8108,    0x9129,    0xa14a,    0xb16b,    0xc18c,    0xd1ad,    0xe1ce,    0xf1ef,
  596.     0x1231,    0x0210,    0x3273,    0x2252,    0x52b5,    0x4294,    0x72f7,    0x62d6,
  597.     0x9339,    0x8318,    0xb37b,    0xa35a,    0xd3bd,    0xc39c,    0xf3ff,    0xe3de,
  598.     0x2462,    0x3443,    0x0420,    0x1401,    0x64e6,    0x74c7,    0x44a4,    0x5485,
  599.     0xa56a,    0xb54b,    0x8528,    0x9509,    0xe5ee,    0xf5cf,    0xc5ac,    0xd58d,
  600.     0x3653,    0x2672,    0x1611,    0x0630,    0x76d7,    0x66f6,    0x5695,    0x46b4,
  601.     0xb75b,    0xa77a,    0x9719,    0x8738,    0xf7df,    0xe7fe,    0xd79d,    0xc7bc,
  602.     0x48c4,    0x58e5,    0x6886,    0x78a7,    0x0840,    0x1861,    0x2802,    0x3823,
  603.     0xc9cc,    0xd9ed,    0xe98e,    0xf9af,    0x8948,    0x9969,    0xa90a,    0xb92b,
  604.     0x5af5,    0x4ad4,    0x7ab7,    0x6a96,    0x1a71,    0x0a50,    0x3a33,    0x2a12,
  605.     0xdbfd,    0xcbdc,    0xfbbf,    0xeb9e,    0x9b79,    0x8b58,    0xbb3b,    0xab1a,
  606.     0x6ca6,    0x7c87,    0x4ce4,    0x5cc5,    0x2c22,    0x3c03,    0x0c60,    0x1c41,
  607.     0xedae,    0xfd8f,    0xcdec,    0xddcd,    0xad2a,    0xbd0b,    0x8d68,    0x9d49,
  608.     0x7e97,    0x6eb6,    0x5ed5,    0x4ef4,    0x3e13,    0x2e32,    0x1e51,    0x0e70,
  609.     0xff9f,    0xefbe,    0xdfdd,    0xcffc,    0xbf1b,    0xaf3a,    0x9f59,    0x8f78,
  610.     0x9188,    0x81a9,    0xb1ca,    0xa1eb,    0xd10c,    0xc12d,    0xf14e,    0xe16f,
  611.     0x1080,    0x00a1,    0x30c2,    0x20e3,    0x5004,    0x4025,    0x7046,    0x6067,
  612.     0x83b9,    0x9398,    0xa3fb,    0xb3da,    0xc33d,    0xd31c,    0xe37f,    0xf35e,
  613.     0x02b1,    0x1290,    0x22f3,    0x32d2,    0x4235,    0x5214,    0x6277,    0x7256,
  614.     0xb5ea,    0xa5cb,    0x95a8,    0x8589,    0xf56e,    0xe54f,    0xd52c,    0xc50d,
  615.     0x34e2,    0x24c3,    0x14a0,    0x0481,    0x7466,    0x6447,    0x5424,    0x4405,
  616.     0xa7db,    0xb7fa,    0x8799,    0x97b8,    0xe75f,    0xf77e,    0xc71d,    0xd73c,
  617.     0x26d3,    0x36f2,    0x0691,    0x16b0,    0x6657,    0x7676,    0x4615,    0x5634,
  618.     0xd94c,    0xc96d,    0xf90e,    0xe92f,    0x99c8,    0x89e9,    0xb98a,    0xa9ab,
  619.     0x5844,    0x4865,    0x7806,    0x6827,    0x18c0,    0x08e1,    0x3882,    0x28a3,
  620.     0xcb7d,    0xdb5c,    0xeb3f,    0xfb1e,    0x8bf9,    0x9bd8,    0xabbb,    0xbb9a,
  621.     0x4a75,    0x5a54,    0x6a37,    0x7a16,    0x0af1,    0x1ad0,    0x2ab3,    0x3a92,
  622.     0xfd2e,    0xed0f,    0xdd6c,    0xcd4d,    0xbdaa,    0xad8b,    0x9de8,    0x8dc9,
  623.     0x7c26,    0x6c07,    0x5c64,    0x4c45,    0x3ca2,    0x2c83,    0x1ce0,    0x0cc1,
  624.     0xef1f,    0xff3e,    0xcf5d,    0xdf7c,    0xaf9b,    0xbfba,    0x8fd9,    0x9ff8,
  625.     0x6e17,    0x7e36,    0x4e55,    0x5e74,    0x2e93,    0x3eb2,    0x0ed1,    0x1ef0
  626. };
  627.  
  628. void CRC_Init(unsigned short *crcvalue)
  629. {
  630.     *crcvalue = CRC_INIT_VALUE;
  631. }
  632.  
  633. void CRC_ProcessByte(unsigned short *crcvalue, byte data)
  634. {
  635.     *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
  636. }
  637.  
  638. unsigned short CRC_Value(unsigned short crcvalue)
  639. {
  640.     return crcvalue ^ CRC_XOR_VALUE;
  641. }
  642. //=============================================================================
  643.  
  644. /*
  645. ============
  646. PR_WriteProgdefs
  647.  
  648. Writes the global and entity structures out
  649. Returns a crc of the header, to be stored in the progs file for comparison
  650. at load time.
  651. ============
  652. */
  653. int    PR_WriteProgdefs (char *filename)
  654. {
  655.     def_t    *d;
  656.     FILE    *f;
  657.     unsigned short        crc;
  658.     int        c;
  659.     
  660.     printf ("writing %s\n", filename);
  661.     f = fopen (filename, "w");
  662.     
  663. // print global vars until the first field is defined
  664.     fprintf (f,"\n/* file generated by qcc, do not modify */\n\ntypedef struct\n{\tint\tpad[%i];\n", RESERVED_OFS);
  665.     for (d=pr.def_head.next ; d ; d=d->next)
  666.     {
  667.         if (!strcmp (d->name, "end_sys_globals"))
  668.             break;
  669.             
  670.         switch (d->type->type)
  671.         {
  672.         case ev_float:
  673.             fprintf (f, "\tfloat\t%s;\n",d->name);
  674.             break;
  675.         case ev_vector:
  676.             fprintf (f, "\tvec3_t\t%s;\n",d->name);
  677.             d=d->next->next->next;    // skip the elements
  678.             break;
  679.         case ev_string:
  680.             fprintf (f,"\tstring_t\t%s;\n",d->name);
  681.             break;
  682.         case ev_function:
  683.             fprintf (f,"\tfunc_t\t%s;\n",d->name);
  684.             break;
  685.         case ev_entity:
  686.             fprintf (f,"\tint\t%s;\n",d->name);
  687.             break;
  688.         default:
  689.             fprintf (f,"\tint\t%s;\n",d->name);
  690.             break;
  691.         }
  692.     }
  693.     fprintf (f,"} globalvars_t;\n\n");
  694.  
  695. // print all fields
  696.     fprintf (f,"typedef struct\n{\n");
  697.     for (d=pr.def_head.next ; d ; d=d->next)
  698.     {
  699.         if (!strcmp (d->name, "end_sys_fields"))
  700.             break;
  701.             
  702.         if (d->type->type != ev_field)
  703.             continue;
  704.             
  705.         switch (d->type->aux_type->type)
  706.         {
  707.         case ev_float:
  708.             fprintf (f,"\tfloat\t%s;\n",d->name);
  709.             break;
  710.         case ev_vector:
  711.             fprintf (f,"\tvec3_t\t%s;\n",d->name);
  712.             d=d->next->next->next;    // skip the elements
  713.             break;
  714.         case ev_string:
  715.             fprintf (f,"\tstring_t\t%s;\n",d->name);
  716.             break;
  717.         case ev_function:
  718.             fprintf (f,"\tfunc_t\t%s;\n",d->name);
  719.             break;
  720.         case ev_entity:
  721.             fprintf (f,"\tint\t%s;\n",d->name);
  722.             break;
  723.         default:
  724.             fprintf (f,"\tint\t%s;\n",d->name);
  725.             break;
  726.         }
  727.     }
  728.     fprintf (f,"} entvars_t;\n\n");
  729.     
  730.     fclose (f);
  731.     
  732. // do a crc of the file
  733.     CRC_Init (&crc);
  734.     f = fopen (filename, "r+");
  735.     while ((c = fgetc(f)) != EOF)
  736.         CRC_ProcessByte (&crc, c);
  737.         
  738.     fprintf (f,"#define PROGHEADER_CRC %i\n", crc);
  739.     fclose (f);
  740.  
  741.     return crc;
  742. }
  743.  
  744.  
  745. void PrintFunction (char *name)
  746. {
  747.     int        i;
  748.     dstatement_t    *ds;
  749.     dfunction_t        *df;
  750.     
  751.     for (i=0 ; i<numfunctions ; i++)
  752.         if (!strcmp (name, strings + functions[i].s_name))
  753.             break;
  754.     if (i==numfunctions)
  755.         Error ("No function names \"%s\"", name);
  756.     df = functions + i;    
  757.     
  758.     printf ("Statements for %s:\n", name);
  759.     ds = statements + df->first_statement;
  760.     while (1)
  761.     {
  762.         PR_PrintStatement (ds);
  763.         if (!ds->op)
  764.             break;
  765.         ds++;
  766.     }
  767. }
  768.  
  769. /*
  770. ==============================================================================
  771.  
  772. DIRECTORY COPYING / PACKFILE CREATION
  773.  
  774. ==============================================================================
  775. */
  776.  
  777. typedef struct
  778. {
  779.     char    name[56];
  780.     int        filepos, filelen;
  781. } packfile_t;
  782.  
  783. typedef struct
  784. {
  785.     char    id[4];
  786.     int        dirofs;
  787.     int        dirlen;
  788. } packheader_t;
  789.  
  790. packfile_t    pfiles[4096], *pf;
  791. int            packhandle;
  792. int            packbytes;
  793.  
  794. void Sys_mkdir (char *path)
  795. {
  796.     if (mkdir (path, 0777) != -1)
  797.         return;
  798.     if (errno != EEXIST)
  799.         Error ("mkdir %s: %s",path, strerror(errno)); 
  800. }
  801.  
  802. /*
  803. ============
  804. CreatePath
  805. ============
  806. */
  807. void    CreatePath (char *path)
  808. {
  809.     char    *ofs;
  810.     
  811.     for (ofs = path+1 ; *ofs ; ofs++)
  812.     {
  813.         if (*ofs == '/')
  814.         {    // create the directory
  815.             *ofs = 0;
  816.             Sys_mkdir (path);
  817.             *ofs = '/';
  818.         }
  819.     }
  820. }
  821.  
  822.  
  823. /*
  824. ===========
  825. PackFile
  826.  
  827. Copy a file into the pak file
  828. ===========
  829. */
  830. void PackFile (char *src, char *name)
  831. {
  832.     int        in;
  833.     int        remaining, count;
  834.     char    buf[4096];
  835.     
  836.     if ( (byte *)pf - (byte *)pfiles > sizeof(pfiles) )
  837.         Error ("Too many files in pak file");
  838.     
  839.     in = SafeOpenRead (src);
  840.     remaining = filelength (in);
  841.  
  842.     pf->filepos = LittleLong (lseek (packhandle, 0, SEEK_CUR));
  843.     pf->filelen = LittleLong (remaining);
  844.     strcpy (pf->name, name);
  845.     printf ("%64s : %7i\n", pf->name, remaining);
  846.  
  847.     packbytes += remaining;
  848.     
  849.     while (remaining)
  850.     {
  851.         if (remaining < sizeof(buf))
  852.             count = remaining;
  853.         else
  854.             count = sizeof(buf);
  855.         SafeRead (in, buf, count);
  856.         SafeWrite (packhandle, buf, count);
  857.         remaining -= count;
  858.     }
  859.  
  860.     close (in);
  861.     pf++;
  862. }
  863.  
  864.  
  865. /*
  866. ===========
  867. CopyFile
  868.  
  869. Copies a file, creating any directories needed
  870. ===========
  871. */
  872. void CopyFile (char *src, char *dest)
  873. {
  874.     int        in, out;
  875.     int        remaining, count;
  876.     char    buf[4096];
  877.     
  878.     printf ("%s to %s\n", src, dest);
  879.  
  880.     in = SafeOpenRead (src);
  881.     remaining = filelength (in);
  882.     
  883.     CreatePath (dest);
  884.     out = SafeOpenWrite (dest);
  885.     
  886.     while (remaining)
  887.     {
  888.         if (remaining < sizeof(buf))
  889.             count = remaining;
  890.         else
  891.             count = sizeof(buf);
  892.         SafeRead (in, buf, count);
  893.         SafeWrite (out, buf, count);
  894.         remaining -= count;
  895.     }
  896.  
  897.     close (in);
  898.     close (out);    
  899. }
  900.  
  901.  
  902. /*
  903. ===========
  904. CopyFiles
  905. ===========
  906. */
  907. void CopyFiles (void)
  908. {
  909.     int        i, p;
  910.     char    srcdir[1024], destdir[1024];
  911.     char    srcfile[1024], destfile[1024];
  912.     int        copytype;
  913.     char    name[1024];
  914.     packheader_t    header;
  915.     int        dirlen;
  916.     int        blocknum;
  917.     unsigned short        crc;
  918.  
  919.     printf ("%3i unique precache_sounds\n", numsounds);
  920.     printf ("%3i unique precache_models\n", nummodels);
  921.     
  922.     copytype = 0;
  923.  
  924.     p = CheckParm ("-copy");
  925.     if (p && p < myargc-2)
  926.     {    // create a new directory tree
  927.         copytype = 1;
  928.  
  929.         strcpy (srcdir, myargv[p+1]);
  930.         strcpy (destdir, myargv[p+2]);
  931.         if (srcdir[strlen(srcdir)-1] != '/')
  932.             strcat (srcdir, "/");
  933.         if (destdir[strlen(destdir)-1] != '/')
  934.             strcat (destdir, "/");
  935.     }
  936.  
  937.     blocknum = 1;
  938.     p = CheckParm ("-pak2");
  939.     if (p && p <myargc-2)
  940.         blocknum = 2;
  941.     else
  942.         p = CheckParm ("-pak");
  943.     if (p && p < myargc-2)
  944.     {    // create a pak file
  945.         strcpy (srcdir, myargv[p+1]);
  946.         strcpy (destdir, myargv[p+2]);
  947.         if (srcdir[strlen(srcdir)-1] != '/')
  948.             strcat (srcdir, "/");
  949.         DefaultExtension (destdir, ".pak");
  950.  
  951.         pf = pfiles;
  952.         packhandle = SafeOpenWrite (destdir);
  953.         SafeWrite (packhandle, &header, sizeof(header));    
  954.         copytype = 2;
  955.     }
  956.     
  957.     if (!copytype)
  958.         return;
  959.                 
  960.     for (i=0 ; i<numsounds ; i++)
  961.     {
  962.         if (precache_sounds_block[i] != blocknum)
  963.             continue;
  964.         sprintf (name, "sound/%s", precache_sounds[i]);
  965.         sprintf (srcfile,"%s%s",srcdir, name);
  966.         sprintf (destfile,"%s%s",destdir, name);
  967.         if (copytype == 1)
  968.             CopyFile (srcfile, destfile);
  969.         else
  970.             PackFile (srcfile, name);
  971.     }
  972.     for (i=0 ; i<nummodels ; i++)
  973.     {
  974.         if (precache_models_block[i] != blocknum)
  975.             continue;
  976.         sprintf (srcfile,"%s%s",srcdir, precache_models[i]);
  977.         sprintf (destfile,"%s%s",destdir, precache_models[i]);
  978.         if (copytype == 1)
  979.             CopyFile (srcfile, destfile);
  980.         else
  981.             PackFile (srcfile, precache_models[i]);
  982.     }
  983.     for (i=0 ; i<numfiles ; i++)
  984.     {
  985.         if (precache_files_block[i] != blocknum)
  986.             continue;
  987.         sprintf (srcfile,"%s%s",srcdir, precache_files[i]);
  988.         sprintf (destfile,"%s%s",destdir, precache_files[i]);
  989.         if (copytype == 1)
  990.             CopyFile (srcfile, destfile);
  991.         else
  992.             PackFile (srcfile, precache_files[i]);
  993.     }
  994.     
  995.     if (copytype == 2)
  996.     {
  997.         header.id[0] = 'P';
  998.         header.id[1] = 'A';
  999.         header.id[2] = 'C';
  1000.         header.id[3] = 'K';
  1001.         dirlen = (byte *)pf - (byte *)pfiles;
  1002.         header.dirofs = LittleLong(lseek (packhandle, 0, SEEK_CUR));
  1003.         header.dirlen = LittleLong(dirlen);
  1004.         
  1005.         SafeWrite (packhandle, pfiles, dirlen);
  1006.     
  1007.         lseek (packhandle, 0, SEEK_SET);
  1008.         SafeWrite (packhandle, &header, sizeof(header));
  1009.         close (packhandle);    
  1010.     
  1011.     // do a crc of the file
  1012.         CRC_Init (&crc);
  1013.         for (i=0 ; i<dirlen ; i++)
  1014.             CRC_ProcessByte (&crc, ((byte *)pfiles)[i]);
  1015.     
  1016.         i = pf - pfiles;
  1017.         printf ("%i files packed in %i bytes (%i crc)\n",i, packbytes, crc);
  1018.     }
  1019. }
  1020.  
  1021. //============================================================================
  1022.  
  1023. /*
  1024. ============
  1025. main
  1026. ============
  1027. */
  1028. void main (int argc, char **argv)
  1029. {
  1030.     char    *src;
  1031.     char    *src2;
  1032.     char    filename[1024];
  1033.     int        p, crc;
  1034.     char    sourcedir[1024];
  1035.  
  1036.     myargc = argc;
  1037.     myargv = argv;
  1038.     
  1039.     if ( CheckParm ("-?") || CheckParm ("-help"))
  1040.     {
  1041.         printf ("qcc looks for progs.src in the current directory.\n");
  1042.         printf ("to look in a different directory: qcc -src <directory>\n");
  1043.         printf ("to build a clean data tree: qcc -copy <srcdir> <destdir>\n");
  1044.         printf ("to build a clean pak file: qcc -pak <srcdir> <packfile>\n");
  1045.         printf ("to bsp all bmodels: qcc -bspmodels <gamedir>\n");
  1046.         return;
  1047.     }
  1048.     
  1049.     p = CheckParm ("-src");
  1050.     if (p && p < argc-1 )
  1051.     {
  1052.         strcpy (sourcedir, argv[p+1]);
  1053.         strcat (sourcedir, "/");
  1054.         printf ("Source directory: %s\n", sourcedir);
  1055.     }
  1056.     else
  1057.         strcpy (sourcedir, "");
  1058.  
  1059.     InitData ();
  1060.     
  1061.     sprintf (filename, "%sprogs.src", sourcedir);
  1062.     LoadFile (filename, (void *)&src);
  1063.     
  1064.     src = COM_Parse (src);
  1065.     if (!src)
  1066.         Error ("No destination filename.  qcc -help for info.\n");
  1067.     strcpy (destfile, com_token);
  1068.     printf ("outputfile: %s\n", destfile);
  1069.     
  1070.     pr_dumpasm = false;
  1071.  
  1072.     PR_BeginCompilation (malloc (0x100000), 0x100000);
  1073.  
  1074. // compile all the files
  1075.     do
  1076.     {
  1077.         src = COM_Parse(src);
  1078.         if (!src)
  1079.             break;
  1080.         sprintf (filename, "%s%s", sourcedir, com_token);
  1081.         printf ("compiling %s\n", filename);
  1082.         LoadFile (filename, (void *)&src2);
  1083.  
  1084.         if (!PR_CompileFile (src2, filename) )
  1085.             exit (1);
  1086.             
  1087.     } while (1);
  1088.     
  1089.     if (!PR_FinishCompilation ())
  1090.         Error ("compilation errors");
  1091.  
  1092.     p = CheckParm ("-asm");
  1093.     if (p)
  1094.     {
  1095.         for (p++ ; p<argc ; p++)
  1096.         {
  1097.             if (argv[p][0] == '-')
  1098.                 break;
  1099.             PrintFunction (argv[p]);
  1100.         }
  1101.     }
  1102.     
  1103.     
  1104. // write progdefs.h
  1105.     crc = PR_WriteProgdefs ("progdefs.h");
  1106.     
  1107. // write data file
  1108.     WriteData (crc);
  1109.     
  1110. // regenerate bmodels if -bspmodels
  1111.     BspModels ();
  1112.  
  1113. // report / copy the data files
  1114.     CopyFiles ();
  1115. }
  1116.